#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Gradio前端应用
提供录音、转录、摘要生成和飞书推送的Web界面
"""

import gradio as gr
import os
import json
import time
import threading
from datetime import datetime
from pathlib import Path
import numpy as np

# 导入后端模块
from audio_recorder import AudioRecorder
from automation_workflow import AutomationWorkflow
from config import get_config

class GradioAudioApp:
    """Gradio音频处理应用"""
    
    def __init__(self):
        """初始化应用"""
        self.config = get_config()
        self.recorder = AudioRecorder(
            sample_rate=self.config.AUDIO_SAMPLE_RATE,
            channels=self.config.AUDIO_CHANNELS
        )
        self.workflow = AutomationWorkflow()
        self.current_recording_file = None
        self.processing_status = "就绪"
        
    def start_recording(self):
        """开始录音"""
        try:
            if self.recorder.is_recording():
                return "录音已在进行中", None, "录音中..."
            
            # 生成录音文件名
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            self.current_recording_file = os.path.join(
                self.config.RECORDINGS_DIR, 
                f"recording_{timestamp}.wav"
            )
            
            self.recorder.start_recording()
            return "录音已开始", None, "录音中..."
            
        except Exception as e:
            return f"录音启动失败: {str(e)}", None, "就绪"
    
    def stop_recording(self):
        """停止录音"""
        try:
            if not self.recorder.is_recording():
                return "当前没有录音", None, "就绪"
            
            # 停止录音并保存文件
            saved_file = self.recorder.stop_recording(self.current_recording_file)
            
            if saved_file and os.path.exists(saved_file):
                return f"录音已保存: {os.path.basename(saved_file)}", saved_file, "录音完成"
            else:
                return "录音保存失败", None, "就绪"
                
        except Exception as e:
            return f"停止录音失败: {str(e)}", None, "就绪"
    
    def process_and_push(self, audio_file, auto_push=True):
        """处理音频文件并推送到飞书 - 直接使用原始文件，无预处理"""
        if not audio_file:
            return "请先录制或上传音频", "", "", "", "就绪"
        
        try:
            self.processing_status = "处理中..."
            
            # 直接使用上传的原始文件路径，不进行任何转换
            audio_file_path = audio_file
            
            # 验证文件是否存在
            if not os.path.exists(audio_file_path):
                return "❌ 音频文件不存在", "", "", "", "错误"
            
            # 检查文件大小限制
            file_size = os.path.getsize(audio_file_path) / (1024 * 1024)  # MB
            if file_size > 200:  # 200MB限制
                return "❌ 文件过大(>200MB)", "", "", "", "错误"
            
            # 使用自动化工作流处理音频 - 直接传入原始文件
            result = self.workflow.process_audio_file(audio_file_path, auto_push=auto_push)
            
            if result.get("status") == "success":
                # 从正确的位置提取标题和摘要
                llm_step = result.get("steps", {}).get("llm_processing", {})
                title = llm_step.get("title", "")
                summary = llm_step.get("summary", "")
                
                # 格式化摘要显示
                if isinstance(summary, list):
                    formatted_summary = "\n".join(summary)
                else:
                    formatted_summary = summary
                
                # 长度限制
                max_status_len = 100
                max_title_len = 50
                max_summary_len = 500
                max_link_len = 150
                
                # 压缩标题
                compressed_title = title[:max_title_len] + "..." if len(title) > max_title_len else title
                
                # 压缩摘要
                if len(formatted_summary) > max_summary_len:
                    sentences = formatted_summary.split('。')
                    compressed_summary = ""
                    for sentence in sentences:
                        if len(compressed_summary) + len(sentence) + 1 <= max_summary_len - 3:
                            compressed_summary += sentence + "。"
                        else:
                            break
                    compressed_summary = compressed_summary.rstrip('。') + "..."
                else:
                    compressed_summary = formatted_summary
                
                # 处理飞书推送结果
                status = "✅ 处理完成"
                feishu_link = ""
                
                if auto_push:
                    feishu_step = result.get("steps", {}).get("feishu_push", {})
                    if feishu_step.get("status") == "success":
                        # 直接从配置文件读取 app_token 并构造链接
                        try:
                            bitable_config_path = os.path.join(os.path.dirname(__file__), 'bitable', 'bitable_config.json')
                            if os.path.exists(bitable_config_path):
                                with open(bitable_config_path, 'r', encoding='utf-8') as f:
                                    bitable_config = json.load(f)
                                    app_token = bitable_config.get('app_token')
                                    if app_token:
                                        # 直接使用固定前缀构造飞书链接
                                        bitableUrl = f"https://feishu.cn/base/{app_token}"
                                        feishu_link = f'<a href="{bitableUrl[:max_link_len]}" target="_blank">🔗 飞书表格</a>'
                        except Exception as e:
                            print(f"构造飞书链接时出错: {e}")
                            feishu_link = "🔗 飞书表格 (链接构造失败)"
                        
                        status = "✅ 已推送到飞书"
                    else:
                        status = "⚠️ 推送失败"
                        feishu_link = "❌ 推送失败"
                else:
                    feishu_link = "未启用推送"
                
                self.processing_status = "完成"
                
                return (
                    status[:max_status_len],
                    compressed_title,
                    compressed_summary,
                    feishu_link,
                    "完成"
                )
            else:
                error_msg = result.get("error", "处理失败")
                self.processing_status = "错误"
                return f"❌ {error_msg[:50]}...", "", "", "❌ 失败", "错误"
                
        except Exception as e:
            self.processing_status = "错误"
            error_str = str(e)[:50]
            return f"❌ {error_str}...", "", "", "❌ 异常", "错误"
    
    def get_recording_status(self):
        """获取录音状态"""
        if self.recorder.is_recording():
            return "🔴 录音中..."
        else:
            return "⚪ 未录音"
    
    def get_processing_status(self):
        """获取处理状态"""
        return self.processing_status
    
    def create_interface(self):
        """创建Gradio界面"""
        
        # 自定义CSS样式
        css = """
        .status-box {
            padding: 10px;
            border-radius: 5px;
            margin: 5px 0;
        }
        .recording-status {
            background-color: #f0f8ff;
            border: 1px solid #4169e1;
        }
        .processing-status {
            background-color: #f5f5f5;
            border: 1px solid #808080;
        }
        """
        
        with gr.Blocks(css=css, title="AI音频摘要助手") as interface:
            gr.Markdown("# 🎙️ AI音频摘要助手")
            gr.Markdown("录制音频或上传原始音频文件，自动生成摘要并推送到飞书多维表格")
            
            with gr.Row():
                with gr.Column(scale=1):
                    # 录音控制区域
                    gr.Markdown("## 📹 录音控制")
                    
                    recording_status = gr.Textbox(
                        label="录音状态",
                        value="⚪ 未录音",
                        interactive=False,
                        elem_classes=["status-box", "recording-status"]
                    )
                    
                    with gr.Row():
                        start_btn = gr.Button("🔴 开始录音", variant="primary")
                        stop_btn = gr.Button("⏹️ 停止录音", variant="secondary")
                    
                    recording_message = gr.Textbox(
                        label="录音信息",
                        interactive=False,
                        lines=2
                    )
                    
                    # 音频文件显示
                    audio_output = gr.Audio(
                        label="录制的音频",
                        interactive=False,
                        type="filepath"  # 直接返回文件路径
                    )
                
                with gr.Column(scale=1):
                    # 处理控制区域
                    gr.Markdown("## ⚙️ 处理控制")
                    
                    processing_status = gr.Textbox(
                        label="处理状态",
                        value="就绪",
                        interactive=False,
                        elem_classes=["status-box", "processing-status"]
                    )
                    
                    auto_push_checkbox = gr.Checkbox(
                        label="自动推送到飞书",
                        value=True
                    )
                    
                    process_btn = gr.Button("🚀 处理并推送", variant="primary", size="lg")
                    
                    process_message = gr.Textbox(
                        label="处理结果",
                        interactive=False,
                        lines=3
                    )
            
            # 结果显示区域
            gr.Markdown("## 📄 处理结果")
            
            with gr.Row():
                title_output = gr.Textbox(
                    label="生成标题",
                    interactive=False,
                    lines=2
                )
                
                summary_output = gr.Textbox(
                    label="内容摘要",
                    interactive=False,
                    lines=8
                )
            
            # 飞书链接显示区域
            feishu_link_output = gr.HTML(
                label="📋 飞书多维表格访问链接",
                value="<p style='color: #666; font-style: italic;'>处理完成后将显示飞书表格链接...</p>"
            )
            
            # 手动上传音频区域 - 支持更多原始格式
            gr.Markdown("## 📁 上传原始音频文件")
            gr.Markdown("**支持格式**: .wav, .m4a, .mp3, .aac, .flac, .ogg, .wma, .amr 等")
            uploaded_audio = gr.Audio(
                label="上传音频文件 (直接使用原始格式，无需转换)",
                type="filepath"  # 直接返回文件路径
            )
            
            upload_process_btn = gr.Button("🚀 处理上传的音频", variant="secondary")
            
            # 事件绑定
            start_btn.click(
                fn=self.start_recording,
                outputs=[recording_message, audio_output, recording_status]
            )
            
            stop_btn.click(
                fn=self.stop_recording,
                outputs=[recording_message, audio_output, recording_status]
            )
            
            process_btn.click(
                fn=self.process_and_push,
                inputs=[audio_output, auto_push_checkbox],
                outputs=[process_message, title_output, summary_output, feishu_link_output, processing_status]
            )
            
            upload_process_btn.click(
                fn=self.process_and_push,
                inputs=[uploaded_audio, auto_push_checkbox],
                outputs=[process_message, title_output, summary_output, feishu_link_output, processing_status]
            )
            
            # 定时更新状态
            def update_status():
                return self.get_recording_status(), self.get_processing_status()
            
            # 页面加载时更新一次状态
            interface.load(
                fn=update_status,
                outputs=[recording_status, processing_status]
            )
        
        return interface

def main():
    """主函数"""
    print("🚀 启动AI音频摘要助手...")
    
    # 创建应用实例
    app = GradioAudioApp()
    
    # 创建界面
    interface = app.create_interface()
    
    # 启动应用
    print("✅ 应用启动成功!")
    print("📱 请在浏览器中访问应用界面")
    
    interface.launch(
        server_name="0.0.0.0",  # 允许外部访问
        server_port=7860,       # 端口号
        share=False,            # 不创建公共链接
        debug=True,             # 调试模式
        show_error=True,        # 显示错误信息
        max_file_size="200mb",  # 文件大小限制
        max_threads=2           # 限制并发线程数
    )

if __name__ == "__main__":
    main()